package jmine.tec.utils;

/**
 * Implementa uma tupla
 * 
 * @author takeshi.fukushima
 * @param <H> o tipo do primeiro elemento
 * @param <T> o tipo do segundo elemento
 */
public interface Tuple<H, T> {

    /**
     * @return o primeiro elemento
     */
    H getHead();

    /**
     * Atalho para {@link #getHead()}
     * 
     * @return H
     */
    H head();

    /**
     * Atalho para {@link #getTail()}
     * 
     * @return T
     */
    T tail();

    /**
     * @return o segundo elemento
     */
    T getTail();

    /**
     * devolve uma nova tupla nao modificavel a partir desta
     * 
     * @return {@link Tuple}
     */
    Tuple<H, T> toUnmodifiable();

    /**
     * Devolve uma nova tupla mutavel a partir desta. Sempre devolve uma nova instancia
     * 
     * @return {@link Tuple}
     */
    Tuple<H, T> toMutable();

    /**
     * Devolve uma nova tuple. Deve ser polimorfico, ou seja, o objeto retornado deve ter exatamente a mesma classe do objeto em cujo metodo
     * foi chamado.
     * 
     * @return {@link Tuple}
     */
    Tuple<H, T> copy();

    /**
     * Inverte esta tupla. A instância devolvida pode ou não ser polimorfica.
     * 
     * @return {@link Tuple}
     */
    Tuple<T, H> invert();

}
